package com.smart.community.region.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.enums.SystemStatusEnum;
import com.smart.community.region.entity.BuildingTypeCategory;
import com.smart.community.region.mapper.BuildingTypeCategoryMapper;
import com.smart.community.region.service.IBuildingTypeCategoryService;
import com.smart.community.region.vo.BuildingTypeCategoryVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 建筑类型基础分类Service实现类
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 */
@Slf4j
@Service
public class BuildingTypeCategoryServiceImpl extends ServiceImpl<BuildingTypeCategoryMapper, BuildingTypeCategory> implements IBuildingTypeCategoryService {

    @Autowired
    private BuildingTypeCategoryMapper buildingTypeCategoryMapper;

    @Override
    @Cacheable(value = "building:type:division:list", key = "'all'", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getDivisionList() {
        log.info("获取划分方式列表");
        try {
            LambdaQueryWrapper<BuildingTypeCategory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BuildingTypeCategory::getCategoryType, "DIVISION")
                   .eq(BuildingTypeCategory::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByAsc(BuildingTypeCategory::getSortOrder);
            
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectList(wrapper);
            return convertToVOList(categories);
        } catch (Exception e) {
            log.error("获取划分方式列表失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "building:type:by:division", key = "#divisionId", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getTypeListByDivision(Long divisionId) {
        log.info("根据划分方式获取类型列表，划分方式ID：{}", divisionId);
        try {
            LambdaQueryWrapper<BuildingTypeCategory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BuildingTypeCategory::getParentId, divisionId)
                   .eq(BuildingTypeCategory::getCategoryType, "TYPE")
                   .eq(BuildingTypeCategory::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByAsc(BuildingTypeCategory::getSortOrder);
            
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectList(wrapper);
            return convertToVOList(categories);
        } catch (Exception e) {
            log.error("根据划分方式获取类型列表失败，划分方式ID：{}", divisionId, e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "building:type:by:ids", key = "#ids.toString()", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getTypeListByIds(List<Long> ids) {
        log.info("根据ID列表获取类型详情，ID列表：{}", ids);
        try {
            if (CollectionUtils.isEmpty(ids)) {
                return new ArrayList<>();
            }
            
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectByIds(ids);
            return convertToVOList(categories);
        } catch (Exception e) {
            log.error("根据ID列表获取类型详情失败，ID列表：{}", ids, e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "building:type:top:level", key = "'all'", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getTopLevelCategories() {
        log.info("获取所有顶级分类（划分方式）");
        try {
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectTopLevelCategories();
            return convertToVOList(categories);
        } catch (Exception e) {
            log.error("获取所有顶级分类失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "building:type:by:category:type", key = "#categoryType", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getCategoriesByType(String categoryType) {
        log.info("根据分类类型获取分类列表，分类类型：{}", categoryType);
        try {
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectByCategoryType(categoryType);
            return convertToVOList(categories);
        } catch (Exception e) {
            log.error("根据分类类型获取分类列表失败，分类类型：{}", categoryType, e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "building:type:by:division:type", key = "#divisionType", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getCategoriesByDivisionType(String divisionType) {
        log.info("根据划分方式获取分类列表，划分方式：{}", divisionType);
        try {
            List<BuildingTypeCategory> categories = buildingTypeCategoryMapper.selectByDivisionType(divisionType);
            return convertToVOList(categories);
        } catch (Exception e) {
            log.error("根据划分方式获取分类列表失败，划分方式：{}", divisionType, e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "building:type:tree", key = "'all'", unless = "#result == null or #result.isEmpty()")
    public List<BuildingTypeCategoryVO> getCategoryTree() {
        log.info("获取分类树形结构");
        try {
            // 获取所有启用的分类
            LambdaQueryWrapper<BuildingTypeCategory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BuildingTypeCategory::getStatus, SystemStatusEnum.ENABLED.getCode())
                   .orderByAsc(BuildingTypeCategory::getSortOrder);
            
            List<BuildingTypeCategory> allCategories = buildingTypeCategoryMapper.selectList(wrapper);
            
            // 转换为VO
            List<BuildingTypeCategoryVO> allCategoryVOs = convertToVOList(allCategories);
            
            // 构建树形结构
            return buildCategoryTree(allCategoryVOs);
        } catch (Exception e) {
            log.error("获取分类树形结构失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    @CacheEvict(value = {
        "building:type:division:list",
        "building:type:by:division",
        "building:type:by:ids",
        "building:type:top:level",
        "building:type:by:category:type",
        "building:type:by:division:type",
        "building:type:tree"
    }, allEntries = true)
    public void clearAllBuildingTypeCache() throws Exception {
        log.info("清除所有建筑类型缓存");
        // 方法体可以为空，@CacheEvict注解会自动清除指定缓存区域的所有条目
    }

    @Override
    @CacheEvict(value = "building:type:by:division", key = "#divisionId")
    public void clearBuildingTypeCacheByDivision(Long divisionId) throws Exception {
        log.info("清除指定划分方式的建筑类型缓存，划分方式ID：{}", divisionId);
        // 方法体可以为空，@CacheEvict注解会自动清除指定键的缓存
    }

    @Override
    @CacheEvict(value = "building:type:by:category:type", key = "#categoryType")
    public void clearBuildingTypeCacheByCategoryType(String categoryType) throws Exception {
        log.info("清除指定分类类型的建筑类型缓存，分类类型：{}", categoryType);
        // 方法体可以为空，@CacheEvict注解会自动清除指定键的缓存
    }

    /**
     * 转换为VO列表
     */
    private List<BuildingTypeCategoryVO> convertToVOList(List<BuildingTypeCategory> categories) {
        if (CollectionUtils.isEmpty(categories)) {
            return new ArrayList<>();
        }
        
        return categories.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 转换为VO
     */
    private BuildingTypeCategoryVO convertToVO(BuildingTypeCategory category) {
        BuildingTypeCategoryVO vo = new BuildingTypeCategoryVO();
        BeanUtils.copyProperties(category, vo);
        return vo;
    }

    /**
     * 构建分类树形结构
     */
    private List<BuildingTypeCategoryVO> buildCategoryTree(List<BuildingTypeCategoryVO> allCategories) {
        if (CollectionUtils.isEmpty(allCategories)) {
            return new ArrayList<>();
        }
        
        // 按父ID分组
        Map<Long, List<BuildingTypeCategoryVO>> parentMap = allCategories.stream()
                .collect(Collectors.groupingBy(category -> 
                    category.getParentId() == null ? 0L : category.getParentId()));
        
        // 获取顶级分类
        List<BuildingTypeCategoryVO> topLevelCategories = parentMap.get(0L);
        if (CollectionUtils.isEmpty(topLevelCategories)) {
            return new ArrayList<>();
        }
        
        // 递归设置子分类
        topLevelCategories.forEach(category -> setChildren(category, parentMap));
        
        return topLevelCategories;
    }

    /**
     * 递归设置子分类
     */
    private void setChildren(BuildingTypeCategoryVO parent, Map<Long, List<BuildingTypeCategoryVO>> parentMap) {
        List<BuildingTypeCategoryVO> children = parentMap.get(parent.getId());
        if (!CollectionUtils.isEmpty(children)) {
            parent.setChildren(children);
            children.forEach(child -> setChildren(child, parentMap));
        }
    }
}
